home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / include / scribus-ng / desaxe / digester.h < prev    next >
Encoding:
C/C++ Source or Header  |  2009-03-09  |  8.1 KB  |  410 lines

  1. /*
  2.  *  digester.h
  3.  *  
  4.  *
  5.  *  Created by Andreas Vox on 02.06.06.
  6.  *  Copyright 2006 under GPL2. All rights reserved.
  7.  *
  8.  */
  9.  
  10.  
  11.  
  12. #ifndef DIGESTER_H
  13. #define DIGESTER_H
  14.  
  15. #include <cassert>
  16. #include <iostream>
  17. #include <vector>
  18. #include <map>
  19. #include <string>
  20. #include <typeinfo>
  21.  
  22. #include "desaxe_conf.h"
  23. #include "saxhandler.h"
  24.  
  25.  
  26. //#define DESAXE_DEBUG 1
  27.  
  28. namespace desaxe {
  29.     
  30. class Action;
  31. class RuleState;
  32.  
  33.  
  34. namespace PRIVATE {
  35.     
  36.     class VarPtr
  37.     {
  38.     public:
  39.         void* ptr;
  40.         std::string type;
  41.     };
  42.  
  43.     
  44.     template<class ObjType>
  45.     inline
  46.     VarPtr mkcell(ObjType* obj)
  47.     {
  48.         VarPtr result;
  49.         result.ptr = obj;//    result.ptr = const_cast<void*>(static_cast<const void*>(obj)); //??
  50.         result.type = typeid(obj).name();
  51.         return result;
  52.     }
  53.     
  54.     
  55.     template<class ObjType>
  56.     inline
  57.     void chkcell(const VarPtr& cell, std::vector<VarPtr>* stack = NULL)
  58.     {
  59.         ObjType* dummy = NULL;
  60.         if( cell.type != typeid(dummy).name() )
  61.         {
  62.             std::cerr << "requested type '" << typeid(dummy).name() << "' doesnt match cell type '" << cell.type << "'\n";
  63.             if (stack)
  64.             {
  65.                 int i=0;
  66.                 std::vector<VarPtr>::iterator it;
  67.                 for (it = stack->begin(); it != stack->end(); ++it)
  68.                 {
  69.                     std::cerr << i++ << "\t" << (*it).type << "\t" << (*it).ptr << "\n";
  70.                 }
  71.             }
  72.             assert (false);
  73.         }
  74.     }
  75.     
  76.  
  77.  
  78. class Patch {
  79. public:
  80.     // internal linked list
  81.     Patch* next;
  82.     Patch(Patch* nxt) : next(nxt) {}
  83.     
  84.     virtual void run(VarPtr lnk) = 0;
  85.     virtual ~Patch() {}
  86. };
  87.  
  88.  
  89. } // namespace PRIVATE    
  90.  
  91.  
  92.  
  93. /**
  94.    Digester helps you to create C++ objects from a SAX stream.
  95.    All you have to do is register actions for patterns of element tags
  96.    you expect in your XML stream. These actions can create new objects, set
  97.    attributes, or call methods. Actions operate on intermediate objects which 
  98.    are hold on a stack maintained by Digester.  
  99.  */
  100. class Digester : public SaxHandler {    
  101. public:
  102.     Digester();
  103.     Digester& operator=(const Digester& other);
  104.     virtual ~Digester();
  105.     void addRule(const Xml_string& pattern, Action action);
  106.     
  107.     void parseFile(const Xml_string& filename);
  108.     void parseMemory(const char* data, unsigned int length);
  109.     
  110.     template<class ObjType>
  111.         ObjType*  result();    
  112.     int nrOfErrors() const;
  113.     const Xml_string getError(int i) const;
  114.     
  115. // called by SAX parser:
  116.     void beginDoc();
  117.     void endDoc();
  118.     void begin(const Xml_string& tag, Xml_attr attr);
  119.     void end(const Xml_string& tag);
  120.     void chars(const Xml_string& text);
  121.     
  122. // used by actions:
  123.     void fail();
  124.     void error(const Xml_string& msg);
  125.     
  126.     template<class ObjType>
  127.     ObjType*  top(unsigned int offset = 0);
  128.     
  129.     template<class ObjType>
  130.     ObjType*  bottom(unsigned int offset = 0);
  131.     
  132.     template<class ObjType>
  133.     void setResult(    ObjType* res );
  134.     
  135.     void pop();
  136.     void popn(unsigned int number);
  137.     
  138.     template<class ObjType>
  139.     void push(ObjType* obj);
  140.     
  141. //  used to resolve idrefs and for general storage    
  142.     template<class ObjType>
  143.         ObjType*  lookup(const Xml_string& idref);    
  144.     template<class ObjType>
  145.         void store(const Xml_string& idref, ObjType* res );
  146.     
  147. //  used to resolve idrefs if use is before definition
  148.     template<class LinkType>
  149.         void patchCall(const Xml_string& idref, void (*fun)(LinkType*) );
  150.     template<class ObjType, class LinkType>
  151.         void patchInvoke(const Xml_string& idref, ObjType* obj, void (ObjType::*fun)(LinkType*) );
  152.     
  153.     // used to insert "/" where necessary
  154.     static Xml_string concat(const Xml_string& pattern1, const Xml_string& pattern2);
  155.  
  156. private:
  157.     RuleState* 
  158.         state;
  159.     
  160.     std::vector<PRIVATE::VarPtr> 
  161.         objects;
  162.     
  163.     std::map<Xml_string, PRIVATE::VarPtr> 
  164.         storage;
  165.  
  166.     std::map<Xml_string, PRIVATE::Patch*>
  167.         patches;
  168.     
  169.     PRIVATE::VarPtr 
  170.         result_;
  171.     
  172.     std::vector<Xml_string> 
  173.         errors;
  174. };
  175.  
  176.  
  177.  
  178. template<class ObjType>
  179. inline
  180. ObjType*  Digester::top(unsigned int offset) 
  181. {
  182. #ifdef DESAXE_DEBUG
  183.     std::cerr << "top(" << offset << ") of " << objects.size() << "\n";
  184. #endif
  185.     unsigned int count = objects.size();
  186.     assert (offset < count); 
  187.     PRIVATE::chkcell<ObjType>(objects[count - offset - 1], &objects);
  188. #ifdef DESAXE_DEBUG
  189.     std::cerr << "stack-> " << static_cast<ObjType*>(objects[count - offset - 1].ptr) << "\n";
  190. #endif
  191.     
  192.     return static_cast<ObjType*>(objects[count - offset - 1].ptr);
  193. }
  194.  
  195.  
  196. template<class ObjType>
  197. inline
  198. ObjType*  Digester::bottom(unsigned int offset) 
  199. #ifdef DESAXE_DEBUG
  200.     std::cerr << "bottom(" << offset << ") of " << objects.size() << "\n";
  201. #endif
  202.     unsigned int count = objects.size();
  203.     assert (offset < count); 
  204.     PRIVATE::chkcell<ObjType> (objects[offset]);
  205.     return static_cast<ObjType*>(objects[offset].ptr);
  206. }
  207.  
  208.  
  209. template<class ObjType>
  210. inline
  211. ObjType*  Digester::result() 
  212.     ObjType* dummy = NULL;
  213.     if (result_.type != typeid(dummy).name())
  214.         return NULL;
  215. #ifdef DESAXE_DEBUG
  216.     std::cerr << "result-> " << static_cast<ObjType*>(result_.ptr) << "\n";
  217. #endif
  218.     return static_cast<ObjType*>(result_.ptr);
  219. }
  220.  
  221.  
  222. template<class ObjType>
  223. inline
  224. void Digester::setResult(ObjType* res) 
  225. #ifdef DESAXE_DEBUG
  226.     std::cerr << res << " ->result\n";
  227. #endif
  228.     result_ = PRIVATE::mkcell(res);
  229. }
  230.  
  231.  
  232. inline
  233. void Digester::pop()
  234. {
  235.     assert (1 <= (unsigned int) objects.size());
  236.     objects.pop_back();
  237. }
  238.  
  239. inline
  240. void Digester::popn(unsigned int number)
  241. {
  242.     unsigned int count = (unsigned int) objects.size();
  243.     assert (number <= count);
  244.     objects.resize(count - number);
  245. }
  246.  
  247.  
  248. template<class ObjType>
  249. inline
  250. void Digester::push(ObjType* obj)
  251. {
  252. #ifdef DESAXE_DEBUG
  253.     std::cerr << "stack<- " << obj << "\n";
  254. #endif
  255.     objects.push_back(PRIVATE::mkcell(obj));
  256. }
  257.  
  258.  
  259. // now lookup / store / patch business
  260.  
  261. namespace PRIVATE {
  262.     
  263.     template <class LinkType>
  264.     struct Patch1 : public Patch
  265.     {
  266.         typedef void (*FunType1)(LinkType*);
  267.         FunType1 fun;
  268.         
  269.         Patch1(FunType1 fn, Patch* nxt = NULL) : Patch(nxt), fun(fn) {}
  270.         
  271.         void run(VarPtr link) 
  272.         { 
  273.             fun( static_cast<LinkType*>(link.ptr) ); 
  274.         }
  275.     };
  276.     
  277.     
  278.     template <class ObjType, class LinkType>
  279.         struct Patch2 : public Patch
  280.     {
  281.         typedef void (ObjType::*FunType2)(LinkType*);
  282.         ObjType* obj;
  283.         FunType2 fun;
  284.         
  285.         Patch2(ObjType* ob, FunType2 fn, Patch* nxt = NULL) : Patch(nxt), obj(ob), fun(fn) {}
  286.  
  287.         void run(VarPtr link)
  288.         {
  289.             (obj->*fun)( static_cast<LinkType*>(link.ptr) ); 
  290.         }
  291.     };
  292.     
  293.     
  294.     inline
  295.     void runPatches(Patch*& list, VarPtr link)
  296.     {
  297.         while (list)
  298.         {
  299.             Patch* nxt = list->next;
  300.             list->run(link);
  301.             delete list;
  302.             list = nxt;
  303.         }
  304.     }
  305.     
  306.     inline
  307.     void deletePatches(std::map<Xml_string, Patch*>& patches)
  308.     {
  309.         std::map<Xml_string, Patch*>::iterator it;
  310.         for (it = patches.begin(); it != patches.end(); ++it)
  311.         {
  312.             Patch* list = it->second;
  313.             while (list)
  314.             {
  315.                 Patch* nxt = list->next;
  316.                 delete list;
  317.                 list = nxt;
  318.             }
  319.         }
  320.         patches.clear();
  321.     }
  322.  
  323.     
  324. //    template<> class Patch1<void>;
  325. //    template<> class Patch2<VarPtr,void>;
  326.     
  327. } //namespace PRIVATE
  328.  
  329.  
  330.  
  331. template<class ObjType>
  332. inline
  333. ObjType*  Digester::lookup(const Xml_string& idref) 
  334.     using namespace PRIVATE;
  335.  
  336.     std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
  337.     if (cell == storage.end())
  338.     {
  339. #ifdef DESAXE_DEBUG
  340.         std::cerr << "lookup[" << idref << "]-> NULL\n";
  341. #endif
  342.         return NULL;
  343.     }
  344.     else
  345.     {
  346.         chkcell<ObjType> (cell->second);
  347. #ifdef DESAXE_DEBUG
  348.         std::cerr << "lookup[" << idref << "]-> " << static_cast<ObjType*>(cell->second.ptr) << "\n";
  349. #endif
  350.         return static_cast<ObjType*>(cell->second.ptr);
  351.     }
  352. }
  353.  
  354.  
  355.  
  356. template<class ObjType>
  357. inline
  358. void Digester::store(const Xml_string& idref, ObjType* obj) 
  359. {
  360.     using namespace PRIVATE;
  361. #ifdef DESAXE_DEBUG
  362.     std::cerr << "store[" << idref << "] <- " << obj << "\n";
  363. #endif
  364.     storage[idref] = mkcell(obj);
  365.     runPatches(patches[idref], storage[idref]);
  366. }
  367.  
  368.  
  369.  
  370. template<class LinkType>
  371. void Digester::patchCall(const Xml_string& idref, void (*fun)(LinkType*) )
  372. {
  373.     using namespace PRIVATE;
  374.     
  375.     std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
  376.     if (cell == storage.end())
  377.     {
  378.         patches[idref] = new Patch1<LinkType>(fun, patches[idref] );
  379.     }
  380.     else
  381.     {
  382.         Patch1<LinkType>(fun).run(cell->second);
  383.     }
  384. }
  385.  
  386.  
  387. template<class ObjType, class LinkType>
  388. void Digester::patchInvoke(const Xml_string& idref, ObjType* obj, void (ObjType::*fun)(LinkType*) )
  389. {
  390.     using namespace PRIVATE;
  391.     
  392.     std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
  393.     if (cell == storage.end())
  394.     {
  395.         patches[idref] = new Patch2<ObjType,LinkType>(obj, fun, patches[idref] );
  396.     }
  397.     else
  398.     {
  399.         Patch2<ObjType,LinkType>(obj, fun).run(cell->second);
  400.     }
  401. }
  402.  
  403. } // namespace desaxe
  404.  
  405. #endif
  406.